package com.atguigu.singleton.type6;

/**
 * @program: design-patterns
 * @author: yangshen
 * @description: type6 - 双重检查（线程安全），推荐使用
 * 优缺点说明：
 * 1) Double-Check概念是多线程开发中常使用到的，如代码中所示，我们进行了两
 * 次if (singleton == null)检查，这样就可以保证线程安全了。
 * 2) 这样，实例化代码只用执行一次，后面再次访问时，判断if (singleton == null)，
 * 直接return实例化对象，也避免的反复进行方法同步.
 * 3) 线程安全；延迟加载；效率较高
 * 4) 结论：在实际开发中，推荐使用这种单例设计模式
 * @create: 2022-01-16 11:28
 **/
public class SingleTon {

    public static void main(String[] args) {
        System.out.println("双重检查（线程安全），推荐使用");
        //测试
        SingleTon instance1 = SingleTon.getInstance();
        SingleTon instance2 = SingleTon.getInstance();
        //true
        System.out.println(instance1 == instance2);
        System.out.println("instance1.hashCode() = "+ instance1.hashCode());
        System.out.println("instance2.hashCode() = "+ instance2.hashCode());
    }

    /**
     * 1.构造器私有化，外部不能new
     */
    private SingleTon() {
    }

    /**
     * 2.定义对象实例(volatile 相当于轻量级的synchronized，一个SINGLE_TON有改变都会刷进来)
     */
    private static volatile SingleTon SINGLE_TON ;

    /**
     * 3.提供一个静态的公有方法，加入双重检查代码，解决线程安全问题，同时解决懒加载问题，又保证了效率 推荐使用
     * @return 该对象实例
     */
    public static SingleTon getInstance(){
        if (null == SINGLE_TON){
            //3.1当a,b两个线程同时跑到这，当a线程创建对象并离开后，b线程进来后不会再创建对象
            synchronized (SingleTon.class){
                if (null == SINGLE_TON){
                    SINGLE_TON = new SingleTon();
                }
            }
        }
        return SINGLE_TON;
    }
}
